// 1.引入库
import axios from 'axios'
import { Message } from 'element-ui'
import store from '@/store'
import { getTimeStamp } from '@/utils/auth'
import router from '@/router'
// 封装校验是否超时的函数
const checkTimeout = () => {
  // 1.设定超时时间间隔（2小时）
  const timeout = 1000 * 60 * 60 * 2
  // 2.获取之前的记录
  const loginTime = getTimeStamp()
  // 3.获取当前的时间
  const now = new Date()
  const nowTime = now.getTime()
  // 4.当前时间减去之前的记录如果超过了时间间隔那就算是超时
  return nowTime - loginTime > timeout
}
// 2.创建实例
// create an axios instance
const service = axios.create({
  // 正式请求地址 = 基准路径 + 请求api封装路径
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  // 如果 5000 毫秒都没有响应，就算超时
  timeout: 5000 // request timeout
})

// 请求拦截器
// 这里跟响应拦截器一样，可以接受两个参数
// 1.成功请求后情况的回调（可以拦截到当前请求的配置 一般形参叫 config）
// 2.失败请求的回调（暂时没有失败情况，先写一个占位）
// request interceptor
service.interceptors.request.use(
  config => {
    // 凡是有拦截，请记得放行
    // 前提条件：有token
    if (store.getters.token) {
      // 这里之前只是进行token的注入
      // 现在还要主动介入检查token是否超时
      // 由于超时的逻辑算是复杂, 另外封装一个函数来使用
      const isTimeout = checkTimeout()
      if (isTimeout) {
        // 如果已经超时
        console.log('已超时')
        // 记得超时的时候, 像报错一样, 将当前的请求拒绝掉
        // 还需要 清理 用户数据(其实就是执行登出)
        store.dispatch('user/logout')
        // 跳转到登录页
        router.push('/login')
        return Promise.reject(new Error('请求已超时, 请重试'))
      }
      // 这里我们希望统一添加 token
      // 我们这个项目使用的是 Bearer JWT token 标准
      // 固定标准写法为 'Bearer xxx'
      config.headers.Authorization = `Bearer ${store.getters.token}`
    }
    return config
  },
  err => {
    console.log(err)
    // 2.失败请求的回调（暂时没有失败情况，先写一个占位）
    return Promise.reject('请求失败')
  }
)

// 响应拦截器
// 响应拦截器可以接受两个参数
// 第一个是网络层面成功的回调
// 第二个是网络层面失败的回调
// response interceptor
service.interceptors.response.use(
  res => {
  //  这是网络层面的成功
    const { success, message, data } = res.data
    if (success) {
      // console.log('走到 success')
      // 返回数据
      // 这里是网络成功, 数据也成功
      // 记住一旦拦截了就必须放行不然没数据
      // return res.data.data
      return data
    } else {
    // 数据层面的失败
      // 1. 提示错误
      Message.error(message)
      // 2. 拒绝当前的 promise 继续执行
      return Promise.reject(new Error(message))
    }
  },
  err => {
    // console.log(err)
    console.dir(err)
    // 这里的报错可能性非常多，断网，路径错误，服务器崩溃，都可能
    // 其中有一种就是后端认为我们 token 失效
    // 我们要对这种错误做判断，特殊处理
    // 我们跟后端约定，如果报错的同时给出代码 10002 就是超时
    // 还因为这里的错误很多类型，可能 response 数据不一定存在，所以写更完整的判断更保险
    if (err.response && err.response.data && err.response.data.code === 10002) {
      // 清理数据
      store.dispatch('user/logout')
      // 跳转到登录页
      router.push('/login')
    }
    // 网络层面的失败
    // 1. 提示错误
    Message.error(err.message || '系统繁忙, 请稍后再试')
    // 2.拒绝当前的 promise 继续执行
    return Promise.reject(new Error('系统繁忙, 请稍后再试'))
  }
)

// 暴露
export default service
